package com.example.camera01;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;

public class rtsp extends AppCompatActivity implements MediaRecorder.OnInfoListener, View.OnClickListener {

    private CameraManager mCameraManager;
    private static final int REQUEST_CAMERA_PERMISSION = 1;
    public static final String TAG = "LoginActivity";
    CameraDevice mCameraDevice;
    CameraCaptureSession mCaptureSession;

    private MediaRecorder mMediaRecorder;
    private HandlerThread mHandlerThread;
    private Handler mHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!checkCameraPermission())
            return;
        setContentView(R.layout.main);
        this.findViewById(R.id.stop).setOnClickListener(this);
        startStreaming(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCameraDevice != null) {
            mCameraDevice.close();
        }
    }

    private boolean checkCameraPermission() {
        int cameraPermission1 = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        int cameraPermission2 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        int cameraPermission3 = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
        int cameraPermission4 = ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET);

        if (cameraPermission1 != PackageManager.PERMISSION_GRANTED || cameraPermission2 != PackageManager.PERMISSION_GRANTED
                || cameraPermission3 != PackageManager.PERMISSION_GRANTED||  cameraPermission4 != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET,Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, REQUEST_CAMERA_PERMISSION);
            return false;
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "权限授予成功，可以进行拍照操作 PERMISSION_GRANTED");
                // 权限授予成功，可以进行拍照操作
            } else {
                Log.e(TAG, "权限授予失败，无法进行拍照操作");
                //
            }
        }
    }

    public void startStreaming(Context context) {
        try {
            // 创建 HandlerThread，用于在单独的线程上运行摄像头操作
            mHandlerThread = new HandlerThread("Camera2 Thread");
            mHandlerThread.start();
            mHandler = new Handler(mHandlerThread.getLooper());

            // 获取摄像头管理器
            mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);

            // 获取可以用于录制视频的摄像头列表
            String[] cameraIds = mCameraManager.getCameraIdList();
            for (String cameraId : cameraIds) {
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
                Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
                if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
                    // 如果后置摄像头可用，使用它来录制视频
                    StreamConfigurationMap map = characteristics.get(
                            CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                    Size[] sizes = map.getOutputSizes(MediaRecorder.class);

                    Log.e(TAG,"sizes"+sizes.length);
                    for(Size a: sizes){
                        Log.e(TAG,"a "+ a.toString());
                    }
                    Size size = sizes[3]; // 使用的输出尺寸 :   640  480

                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mCameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                        @Override
                        public void onOpened(@NonNull CameraDevice camera) {
                            try {
                                mCameraDevice = camera;
                                startRecording(camera, size);
                            } catch (CameraAccessException | IOException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onDisconnected(@NonNull CameraDevice camera) {
                            stopStreaming();
                        }

                        @Override
                        public void onError(@NonNull CameraDevice camera, int error) {
                            stopStreaming();
                        }
                    }, mHandler);

                    break;
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void startRecording(CameraDevice camera, Size size) throws CameraAccessException, IOException {
        // 设置输出文件和其他 MediaRecorder 属性
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setVideoSize(size.getWidth(), size.getHeight());
        mMediaRecorder.setVideoFrameRate(60);
        mMediaRecorder.setVideoEncodingBitRate(1024 * 1024);
        mMediaRecorder.setOnInfoListener(this);

        String a  = Environment.getExternalStorageDirectory().toString()+"/test1.mp4";
        Log.e(TAG, "setOutputFile : "+ a);
        mMediaRecorder.setOutputFile(new File(a));
        mMediaRecorder.prepare();

        // 创建 CaptureSession，将Surface作为输出目标
        Surface surface = mMediaRecorder.getSurface();

        try {
            List<OutputConfiguration> outputs = Arrays.asList(
                    new OutputConfiguration(surface));
            SessionConfiguration config = new SessionConfiguration(SessionConfiguration.SESSION_REGULAR,outputs,new Executor() {
                @Override
                public void execute(Runnable command) {
                    Log.e(TAG, "Executor execute ");
                    command.run();
                }
            } ,mCaptureSessionListener);
            camera.createCaptureSession(config);
        } catch (CameraAccessException ex) {
            Log.e(TAG, "Failed to create a capture session", ex);
        }
    }


    final CameraCaptureSession.StateCallback mCaptureSessionListener =
            new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(CameraCaptureSession session) {
                    Log.e(TAG, "Finished configuring camera outputs");
                    mCaptureSession = session;

                    if (mMediaRecorder.getSurface() != null) {
                        try {
                            // Build a request for preview footage
                            CaptureRequest.Builder requestBuilder =
                                    mCameraDevice.createCaptureRequest(mCameraDevice.TEMPLATE_RECORD);
                            requestBuilder.addTarget(mMediaRecorder.getSurface());
                            CaptureRequest previewRequest = requestBuilder.build();

                            // Start displaying preview images
                            try {
                                session.setRepeatingRequest(previewRequest, /*listener*/null,
                                        /*handler*/null);

                                mMediaRecorder.start();
                            } catch (CameraAccessException ex) {
                                Log.e(TAG, "Failed to make repeating preview request", ex);
                            }
                        } catch (CameraAccessException ex) {
                            Log.e(TAG, "Failed to build preview request", ex);
                        }
                    }
                    else {
                        Log.e(TAG, "Holder didn't exist when trying to formulate preview request");
                    }
                }

                @Override
                public void onClosed(CameraCaptureSession session) {
                    Log.e(TAG, "CameraCaptureSession onClosed");
                    mCaptureSession = null;
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession session) {
                    Log.e(TAG, "Configuration error on device '" + mCameraDevice.getId());
                }};
    public void stopStreaming() {
        try {
            if (mMediaRecorder != null) {
                mMediaRecorder.stop();
                mMediaRecorder.release();
                mMediaRecorder = null;
            }
        } catch (Exception e) {
            Log.e(TAG, "stopStreaming: ", e);
        }
        mHandlerThread.quitSafely();
    }

    @Override
    public void onInfo(MediaRecorder mr, int what, int extra) {
        Log.e(TAG, "OnInfoListener: what: "+what);
    }

    @Override
    public void onClick(View v) {
        mMediaRecorder.stop();
        mCaptureSession.close();
    }
}
